package com.example.mytextcamera2;

import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.Face;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.AudioManager;
import android.media.Image;
import android.media.ImageReader;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import com.example.mytextcamera2.awbstrategy.AwbAutoStrategy;
import com.example.mytextcamera2.awbstrategy.AwbCloseStrategy;
import com.example.mytextcamera2.awbstrategy.AwbCloudyStrategy;
import com.example.mytextcamera2.awbstrategy.AwbDaylight;
import com.example.mytextcamera2.awbstrategy.AwbFluorescent;
import com.example.mytextcamera2.awbstrategy.AwbIncandescent;
import com.example.mytextcamera2.awbstrategy.AwbShade;
import com.example.mytextcamera2.awbstrategy.AwbStrategy;
import com.example.mytextcamera2.awbstrategy.AwbTwilight;
import com.example.mytextcamera2.awbstrategy.AwbWarm;
import com.example.mytextcamera2.flashstrategy.AutoStrategy;
import com.example.mytextcamera2.flashstrategy.CloseStrategy;
import com.example.mytextcamera2.flashstrategy.FlashStrategy;
import com.example.mytextcamera2.flashstrategy.KeepOpenStrategy;
import com.example.mytextcamera2.flashstrategy.OpenStrategy;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class Customcamera extends AppCompatActivity implements View.OnClickListener {

    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
    private static final String TAG = "CameraActivity";

    ///为了使照片竖直显示
    static {
        ORIENTATIONS.append(Surface.ROTATION_0, 90);
        ORIENTATIONS.append(Surface.ROTATION_90, 0);
        ORIENTATIONS.append(Surface.ROTATION_180, 270);
        ORIENTATIONS.append(Surface.ROTATION_270, 180);
    }

    SharedPreferences sharedPreferences;//延时存储数字
    SharedPreferences.Editor editor;
    private EditText ed_time;
    private String time;
    private TextView time_show;
    private Handler handler;

    private TextView tv_awb_close,tv_awbstatus;
    private ImageView iv_awb,wb_auto,wb_cloudy_daylight,wb_daylight,wb_fluorescent,
            wb_incandescent,wb_shade,wb_twilight,wb_warm_fluorescent;
    private View mAwbLayout;

    private View mFlashLayout;
    private TextView tv_flashStatus, tv_flashClose, tv_flashOpen, tv_flashKeepOpen, tv_flashAuto;
    private ImageView iv_thumb, iv_changeCamera, iv_flash;
    private SurfaceTexture mSurfaceTexture;
    private TextureView mTextureView;
    private Handler childHandler;
    private Handler mainHandler;
    private int mCameraID;
    private ImageReader mImageReader;
    private CameraDevice mCameraDevice;//摄像头设备
    private CameraManager mCameraManager;
    private CameraCaptureSession mCameraCaptureSession;
    public final int FLASH_ON = 1;
    public final int FLASH_OFF = 2;
    private CaptureRequest.Builder mPreviewRequestBuilder;
    private Surface mSurface;
    private Size mPreviewSize;
    private File file;
    private Button btn_video_aca;
    private Videocamera videocamera;

    public final int BACK_CAMERA = 0; //后置摄像头的CameraId
    public final int FRONT_CAMERA = 1;

    private TextureView rView;//用于标注人脸
    int[] faceDetectModes;
    boolean isFront;
    Paint pb;
    CameraCaptureSession.CaptureCallback previewCallback;//预览回调

//    private Camera mCamera;
//    //private SurfaceView mPreview;
//    private TextureView mTextureView;
//    //private SurfaceHolder mHolder;
//    private SurfaceTexture mTexture;
//    private int cameraId = 0;//声明cameraId属性，ID为1调用前置摄像头，为0调用后置摄像头。此处因有特殊需要故调用前置摄像头
//    private Button btn_cancel_aca, btn_ok_aca, btn_video_aca;
//    private ImageButton btn_photo_aca;
//    private ImageButton btn_switch;
//    //定义照片保存并显示的方法
//    private Camera.PictureCallback mpictureCallback = new Camera.PictureCallback() {
//        @Override
//        public void onPictureTaken(byte[] data, Camera camera) {
//            String mFilePath = Environment.getExternalStorageDirectory().getPath();
//            // 保存图片的文件名
//            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHH:mm:ss");// HH:mm:ss
//            //获取当前时间
//            Date date = new Date(System.currentTimeMillis());
//            mFilePath = mFilePath + "/" + simpleDateFormat.format(date) + "mytest.jpg";
//            File tempfile = new File(mFilePath);//新建一个文件对象tempfile，并保存在某路径中
//            try {
//                FileOutputStream fos = new FileOutputStream(tempfile);
//                fos.write(data);//将照片放入文件中
//                fos.close();//关闭文件
//                Intent intent = new Intent(Customcamera.this, CameraReaultActivity.class);//新建信使对象
//                intent.putExtra("picpath", mFilePath);//打包文件给信使
//                startActivity(intent);//打开新的activity，即打开展示照片的布局界面
//                Customcamera.this.finish();//关闭现有界面
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
//    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);//隐藏标题栏
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//隐藏状态栏
        setContentView(R.layout.activity_customcarmera);
        initView();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == 1) {
            for (int grantResult : grantResults) {
                if (grantResult != PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(this, "对不起，没有权限，无法正常使用相机", Toast.LENGTH_SHORT).show();
                    return;
                }
            }
            initCamera2();
        }
    }

    private void initView() {
        iv_flash = findViewById(R.id.iv_flash);//闪光灯
        iv_thumb = findViewById(R.id.iv_thumb);
        tv_flashStatus = findViewById(R.id.tv_flash_status);
        mTextureView = findViewById(R.id.textureview);
        iv_changeCamera = findViewById(R.id.iv_change);

        mFlashLayout = findViewById(R.id.layout_flash_text);
        tv_flashAuto = mFlashLayout.findViewById(R.id.tv_flash_auto);
        tv_flashClose = mFlashLayout.findViewById(R.id.tv_flash_close);
        tv_flashKeepOpen = mFlashLayout.findViewById(R.id.tv_flash_keep_open);
        tv_flashOpen = mFlashLayout.findViewById(R.id.tv_flash_open);

        iv_awb = findViewById(R.id.iv_awb);//白平衡
        tv_awbstatus = findViewById(R.id.tv_awb_status);
        mAwbLayout = findViewById(R.id.layout_awb_text);
        tv_awb_close = mAwbLayout.findViewById(R.id.tv_awb_close);
        wb_auto = mAwbLayout.findViewById(R.id.wb_auto);
        wb_cloudy_daylight = mAwbLayout.findViewById(R.id.wb_cloudy_daylight);
        wb_daylight = mAwbLayout.findViewById(R.id.wb_daylight);
        wb_fluorescent = mAwbLayout.findViewById(R.id.wb_fluorescent);
        wb_incandescent = mAwbLayout.findViewById(R.id.wb_incandescent);
        wb_shade = mAwbLayout.findViewById(R.id.wb_shade);
        wb_twilight = mAwbLayout.findViewById(R.id.wb_twilight);
        wb_warm_fluorescent = mAwbLayout.findViewById(R.id.wb_warm_fluorescent);

        tv_awb_close.setOnClickListener(this);
        wb_auto.setOnClickListener(this);
        wb_cloudy_daylight.setOnClickListener(this);
        wb_daylight.setOnClickListener(this);
        wb_fluorescent.setOnClickListener(this);
        wb_incandescent.setOnClickListener(this);
        wb_shade.setOnClickListener(this);
        wb_twilight.setOnClickListener(this);
        wb_warm_fluorescent.setOnClickListener(this);

        tv_flashAuto.setOnClickListener(this);
        tv_flashClose.setOnClickListener(this);
        tv_flashKeepOpen.setOnClickListener(this);
        tv_flashOpen.setOnClickListener(this);
        mSurfaceTexture = mTextureView.getSurfaceTexture();
        btn_video_aca = findViewById(R.id.btn_video_aca);//录像按钮

        rView = findViewById(R.id.rView);//人脸框
        rView.setAlpha(0.9f);//隐藏背景色，以免标注人脸时挡住预览画面

        //延时时间的存储
        sharedPreferences = getSharedPreferences("time", MODE_PRIVATE);
        editor = sharedPreferences.edit();
        ed_time = findViewById(R.id.ed_time);//时间输入框
        time_show = findViewById(R.id.time_show);//显示时间

        //在每次初始化达到重启相机并且获得延迟时间的值
        time = sharedPreferences.getString("delaytime", "");//取时间值
        if (time != null) {
            ed_time.setText(time);//在相机再次启动的时候将之前存储的值传给输入框
        }

        //TextureView添加回调
        mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
                // 初始化Camera
                //获取摄像头权限
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
                            || checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                            || checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED
                            || checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                        requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE,
                                Manifest.permission.RECORD_AUDIO, Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
                        findViewById(R.id.btn_control).setClickable(false);
                    } else {
                        initCamera2();
                    }
                } else {
                    initCamera2();
                }
            }

            @Override
            public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {

            }

            @Override
            public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
                // 释放Camera资源
                if (null != mCameraDevice) {
                    mCameraDevice.close();
                    mCameraDevice = null;
                }
                return false;
            }

            @Override
            public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {

            }
        });

        //拍照点击事件
        findViewById(R.id.btn_control).setOnClickListener(v -> {
            tmusic();
            delaytime();//延时时间
            runTimerRunnable();
            takePicture();
        });

        btn_video_aca.setOnClickListener(v -> {
//            findViewById(R.id.btn_stopvideo_aca).setVisibility(View.VISIBLE);
//            findViewById(R.id.btn_startvideo_aca).setVisibility(View.GONE);
            Intent intent = new Intent().setClass(Customcamera.this, Videocamera.class);
            startActivity(intent);
        });

        //点击闪光灯图标
        iv_flash.setOnClickListener(v -> {
            Animation anim = AnimationUtils.loadAnimation(this, R.anim.flash_in);
            mFlashLayout.setAnimation(anim);
            mFlashLayout.setVisibility(View.VISIBLE);
        });

        //点击白平衡图标
        iv_awb.setOnClickListener(v -> {
            Animation animation = AnimationUtils.loadAnimation(this,R.anim.flash_in);
            mAwbLayout.setAnimation(animation);
            mAwbLayout.setVisibility(View.VISIBLE);
        });

        //查看照片
        iv_thumb.setOnClickListener(v -> {
//            File file=new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)+"/temp.jpg");
//            Intent it =new Intent(Intent.ACTION_VIEW);
//            Uri mUri = Uri.parse("file://"+file.getPath());
//            it.setDataAndType(mUri, "image/*");
//            startActivity(it);
            Intent openAlbumIntent = new Intent(Intent.ACTION_VIEW);
            //openAlbumIntent.setType("image/*");
            openAlbumIntent.setType("vnd.android.cursor.dir/image");
            startActivity(openAlbumIntent);//打开相册
        });

        //更换摄像头
        iv_changeCamera.setOnClickListener(v -> changeCamera());

    }

    //拍照声音
    private MediaPlayer mediaPlayer;
    private AudioManager audioManager;

    private void tmusic() {
        audioManager = (AudioManager) getSystemService(Service.AUDIO_SERVICE);
        mediaPlayer = MediaPlayer.create(this, R.raw.music);
//        mediaPlayer.setLooping(true);//循环播放声音
        mediaPlayer.start();

    }

    //关于延时拍照的定义时间存储方法
    public void delaytime() {
        String time = ed_time.getText().toString().trim();//获取编辑框时间
        editor.putString("delaytime", time);//将时间值传入sharedPreferences
        editor.apply();//editor.commit();也可以
    }

    //关于延时拍照的定义延时拍照线程
    private Runnable timerRunnable = new Runnable() {
        @Override
        public void run() {
            if (time.equals("")){
                return;
            }else {
                int times = Integer.parseInt(time);
                for (; times > 0; times--) {
                    time_show.setText("" + times);//.setText("" + times)括号中的参数类型必须为string
                    if (times > 0) {
                        try {
                            Thread.sleep(1000);
                            Log.d("延时", "run: 休眠1s");
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    };

    //关于延时拍照的利用handler对象运行run方法，没有新建函数，在现有函数中调用
    private void runTimerRunnable() {
        //handler.post(timerRunnable);
        new Thread(timerRunnable).run();
    }

    @SuppressLint({"MissingPermission", "NewApi"})
    private void changeCamera() {
        try {
            //先关闭之前的摄像头
            if (mCameraDevice != null) {
                mCameraDevice.close();
                mCameraDevice = null;
            }
            mCameraID ^= 1;
            mCameraManager.openCamera(mCameraID + "", stateCallback, mainHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }


    @SuppressLint("NewApi")
    private void initCamera2() {
        findViewById(R.id.btn_control).setClickable(true);

        HandlerThread handlerThread = new HandlerThread("Camera2");
        handlerThread.start();
        childHandler = new Handler(handlerThread.getLooper());
        mainHandler = new Handler(getMainLooper());


        mCameraID = BACK_CAMERA;//后摄像头
        Log.d(TAG, "initCamera2: " + CameraCharacteristics.LENS_FACING_BACK);
        mImageReader = ImageReader.newInstance(1080, 1920, ImageFormat.JPEG, 1);
        mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() { //可以在这里处理拍照得到的临时照片 例如，写入本地
            @Override
            public void onImageAvailable(ImageReader reader) {
//                mCameraDevice.close();
//                mSurfaceView.setVisibility(View.INVISIBLE);
                // 拿到拍照照片数据
                Image image = reader.acquireNextImage();
                ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                byte[] bytes = new byte[buffer.remaining()];
                buffer.get(bytes);//由缓冲区存入字节数组

                SimpleDateFormat sdf = new SimpleDateFormat(
                        "yyyyMMdd_HHmmss",
                        Locale.US);

                String fname = "IMG_" +
                        sdf.format(new Date())
                        + ".jpg";

                //保存
                Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

                if (bitmap != null) {
                    if (mCameraID == FRONT_CAMERA) {
                        //前置摄像头拍的要先旋转180度
                        bitmap = adjustPhotoRotation(bitmap, 180);
                    }
                    iv_thumb.setImageBitmap(bitmap);//将图片放在预览框中
                    writeToFile(bitmap, fname);//写入文件
                }

                image.close();
            }
        }, mainHandler);
        //获取摄像头管理
        mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        //检查权限
        try {
            mPreviewSize = getMatchingSize2();
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                return;
            }

            //打开摄像头，第一个参数指示打开哪个摄像头，第二个参数stateCallback为相机的状态回调接口，第三个参数用来确定Callback在哪个线程执行，为null的话就在当前线程执行
            mCameraManager.openCamera(mCameraID + "", stateCallback, mainHandler);

            //TODO 人脸检测
            CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(String.valueOf(mCameraID));
            //可用于判断是否支持人脸检测，以及支持到哪种程度
            faceDetectModes = characteristics.get(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES);//支持的人脸检测模式
            int maxFaceCount = characteristics.get(CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT);//支持的最大检测人脸数量

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    Bitmap adjustPhotoRotation(Bitmap bm, final int orientationDegree) {
        Matrix m = new Matrix();
        m.setRotate(orientationDegree, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);

        try {
            Bitmap bm1 = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), m, true);
            return bm1;
        } catch (OutOfMemoryError ex) {
        }
        return null;
    }

    //图片保存
    private void writeToFile(Bitmap bitmap, String bitName) {
        String fileName;
//        File file;
        if (Build.BRAND.equals("Xiaomi")) { // 小米手机
            fileName = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/" + bitName;
        } else { // Meizu 、Oppo
            fileName = Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + bitName;
        }
        file = new File(fileName);
        if (file.exists()) {
            file.delete();
        }
//        FileOutputStream out;
        try {
            FileOutputStream out = new FileOutputStream(file);
            // 格式为 JPEG，照相机拍出的图片为JPEG格式的，PNG格式的不能显示在相册中
            if (bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)) {
                out.flush();
                out.close();
// 插入图库
                MediaStore.Images.Media.insertImage(this.getContentResolver(), file.getAbsolutePath(), fileName, null);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 发送广播，通知刷新图库的显示
        this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + fileName)));
//        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath()+"/temp.jpg");
//        try {
//            OutputStream os = new FileOutputStream(file);
//
//            bitmap.compress(Bitmap.CompressFormat.JPEG,100,os);
//
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        }
    }

    /**
     * 获取支持的最高人脸检测级别
     *
     * @return
     */
    private int getFaceDetectMode() {
        if (faceDetectModes == null) {
            return CaptureRequest.STATISTICS_FACE_DETECT_MODE_FULL;
        } else {
            return faceDetectModes[faceDetectModes.length - 1];
        }
    }

    /**
     * 开始预览
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void takePreview() {
        mSurfaceTexture = mTextureView.getSurfaceTexture();
        //设置TextureView的缓冲区大小
        mPreviewSize = getMatchingSize2();
        mSurfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
        //获取Surface显示预览数据
        Surface mSurface = new Surface(mSurfaceTexture);
        try {
            // 创建预览需要的CaptureRequest.Builder
            mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            // 将SurfaceView的surface作为CaptureRequest.Builder的目标
            mPreviewRequestBuilder.addTarget(mSurface);
            // 创建CameraCaptureSession，该对象负责管理处理预览请求和拍照请求
            mCameraDevice.createCaptureSession(Arrays.asList(mSurface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(CameraCaptureSession cameraCaptureSession) {
                    if (null == mCameraDevice) return;
                    // 当摄像头已经准备好时，开始显示预览
                    mCameraCaptureSession = cameraCaptureSession;
                    try {
                        // 自动对焦
                        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);

                        //设置人脸检测级别
                        mPreviewRequestBuilder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, getFaceDetectMode());

                        // 打开闪光灯
                        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.FLASH_MODE_OFF);
                        // 显示预览
                        CaptureRequest previewRequest = mPreviewRequestBuilder.build();
                        mCameraCaptureSession.setRepeatingRequest(previewRequest, getPreviewCallback(), childHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
                    Toast.makeText(Customcamera.this, "配置失败", Toast.LENGTH_SHORT).show();
                }
            }, childHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化并获取预览回调对象
     *
     * @return
     */
    private CameraCaptureSession.CaptureCallback getPreviewCallback() {
        if (previewCallback == null) {
            previewCallback = new CameraCaptureSession.CaptureCallback() {
                public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                    Customcamera.this.onCameraImagePreviewed(result);
                }
            };
        }
        return previewCallback;
    }

    /**
     * 处理相机画面处理完成事件，获取检测到的人脸坐标，换算并绘制方框
     *
     * @param result
     */
    private void onCameraImagePreviewed(CaptureResult result) {
        Face faces[] = result.get(CaptureResult.STATISTICS_FACES);

        Canvas canvas = rView.lockCanvas();
        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//旧画面清理覆盖

        if (faces.length > 0) {
            for (int i = 0; i < faces.length; i++) {
                Rect fRect = faces[i].getBounds();
                //Log("[R" + i + "]:[left:" + fRect.left + ",top:" + fRect.top + ",right:" + fRect.right + ",bottom:" + fRect.bottom + "]");

                //人脸检测坐标基于相机成像画面尺寸以及坐标原点。此处进行比例换算
                //成像画面与方框绘制画布长宽比比例（同画面角度情况下的长宽比例（此处前后摄像头成像画面相对预览画面倒置（±90°），计算比例时长宽互换））
                float scaleWidth = canvas.getHeight() * 1.0f / mPreviewSize.getWidth();
                float scaleHeight = canvas.getWidth() * 1.0f / mPreviewSize.getHeight();

                //坐标缩放
                int l = (int) (fRect.left * scaleWidth);
                int t = (int) (fRect.top * scaleHeight);
                int r = (int) (fRect.right * scaleWidth);
                int b = (int) (fRect.bottom * scaleHeight);
                //Log("[T" + i + "]:[left:" + l + ",top:" + t + ",right:" + r + ",bottom:" + b + "]");

                //人脸检测坐标基于相机成像画面尺寸以及坐标原点。此处进行坐标转换以及原点(0,0)换算
                //人脸检测：坐标原点为相机成像画面的左上角，left、top、bottom、right以成像画面左上下右为基准
                //画面旋转后：原点位置不一样，根据相机成像画面的旋转角度需要换算到画布的左上角，left、top、bottom、right基准也与原先不一样，
                //如相对预览画面相机成像画面角度为90°那么成像画面坐标的top，在预览画面就为left。如果再翻转，那成像画面的top就为预览画面的right，且坐标起点为右，需要换算到左边
                if (isFront) {
                    //此处前置摄像头成像画面相对于预览画面顺时针90°+翻转。left、top、bottom、right变为bottom、right、top、left，并且由于坐标原点由左上角变为右下角，X,Y方向都要进行坐标换算
                    canvas.drawRect(canvas.getWidth() - b, canvas.getHeight() - r, canvas.getWidth() - t, canvas.getHeight() - l, getPaint());
                } else {
                    //此处后置摄像头成像画面相对于预览画面顺时针270°，left、top、bottom、right变为bottom、left、top、right，并且由于坐标原点由左上角变为左下角，Y方向需要进行坐标换算
                    canvas.drawRect(canvas.getWidth() - b, l, canvas.getWidth() - t, r, getPaint());
                }
            }
        }
        rView.unlockCanvasAndPost(canvas);
    }

    /**
     * 初始化画笔
     */
    private Paint getPaint() {
        if (pb == null) {
            pb = new Paint();
            pb.setColor(Color.BLUE);
            pb.setStrokeWidth(10);
            pb.setStyle(Paint.Style.STROKE);//使绘制的矩形中空
        }
        return pb;
    }


    @SuppressLint("NewApi")
    public void changeFlash(int type) {
        try {
            CaptureRequest.Builder requestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            requestBuilder.addTarget(mSurface);
            if (type == FLASH_ON)
                requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
            else if (type == FLASH_OFF)
                requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.FLASH_MODE_OFF);
            mCameraCaptureSession.setRepeatingRequest(requestBuilder.build(), null, childHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 摄像头创建监听
     */
    private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        @Override
        public void onOpened(CameraDevice camera) {//打开摄像头
            mCameraDevice = camera;
            //开启预览
            takePreview();
        }

        @Override
        public void onDisconnected(CameraDevice camera) {//关闭摄像头
            if (null != mCameraDevice) {
                mCameraDevice.close();
                Customcamera.this.mCameraDevice = null;
            }
        }

        @Override
        public void onError(CameraDevice camera, int error) {//发生错误
            Toast.makeText(Customcamera.this, "摄像头开启失败", Toast.LENGTH_SHORT).show();
        }
    };

    /**
     * 拍照
     */
    @SuppressLint("NewApi")
    private void takePicture() {
        if (mCameraDevice == null) return;
        // 创建拍照需要的CaptureRequest.Builder
        final CaptureRequest.Builder captureRequestBuilder;
        try {
            captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            // 将imageReader的surface作为CaptureRequest.Builder的目标
            captureRequestBuilder.addTarget(mImageReader.getSurface());
            // 自动对焦
            captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            // 自动曝光
            captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
            // 获取手机方向
            int rotation = getWindowManager().getDefaultDisplay().getRotation();
            // 根据设备方向计算设置照片的方向
            captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
            //拍照
            CaptureRequest mCaptureRequest = captureRequestBuilder.build();
            mCameraCaptureSession.capture(mCaptureRequest, null, childHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    //闪光灯
    @Override
    public void onClick(View v) {
        FlashStrategy strategy = null;
        AwbStrategy awbStrategy = null;
        switch (v.getId()) {
            case R.id.tv_flash_close:
                strategy = new CloseStrategy();
                tv_flashStatus.setText("关闭");
                break;
            case R.id.tv_flash_auto:
                tv_flashStatus.setText("自动");
                strategy = new AutoStrategy();
                break;
            case R.id.tv_flash_open:
                tv_flashStatus.setText("打开");
                strategy = new OpenStrategy();
                break;
            case R.id.tv_flash_keep_open:
                tv_flashStatus.setText("常亮");
                strategy = new KeepOpenStrategy();
                break;
            case R.id.tv_awb_close:
                tv_awbstatus.setText("关闭");
                awbStrategy = new AwbCloseStrategy();
                break;
            case R.id.wb_auto:
                tv_awbstatus.setText("自动");
                awbStrategy = new AwbAutoStrategy();
                break;
            case R.id.wb_cloudy_daylight:
                tv_awbstatus.setText("多云");
                awbStrategy = new AwbCloudyStrategy();
                break;
            case R.id.wb_daylight:
                tv_awbstatus.setText("日光");
                awbStrategy = new AwbDaylight();
                break;
            case R.id.wb_fluorescent:
                tv_awbstatus.setText("荧光灯");
                awbStrategy = new AwbFluorescent();
                break;
            case R.id.wb_incandescent:
                tv_awbstatus.setText("白炽灯");
                awbStrategy = new AwbIncandescent();
                break;
            case R.id.wb_shade:
                tv_awbstatus.setText("无阳光");
                awbStrategy = new AwbShade();
                break;
            case R.id.wb_twilight:
                tv_awbstatus.setText("日出");
                awbStrategy = new AwbTwilight();
                break;
            case R.id.wb_warm_fluorescent:
                tv_awbstatus.setText("暖荧光");
                awbStrategy = new AwbWarm();
                break;
        }
        //说明点击了文字 切换闪光灯
        if (strategy != null) {
            //重新设置背景颜色
            clearAllFlashTextBackground(v.getId());
            //消失动画
            closeFlashLayout();
            //重新设置闪光灯
            strategy.setCaptureRequest(mPreviewRequestBuilder, mCameraCaptureSession, childHandler);
        }
        if (awbStrategy != null){
            //重新设置背景颜色
            clearAllAwbTextBackground(v.getId());
            //消失动画
            closeFlashLayout();
            //重新设置白平衡
            awbStrategy.setCaptureRequest(mPreviewRequestBuilder,mCameraCaptureSession,childHandler);
        }

    }

    public void closeFlashLayout() {
        Animation anim = AnimationUtils.loadAnimation(this, R.anim.flash_out);
        mFlashLayout.setAnimation(anim);
        mFlashLayout.setVisibility(View.GONE);
        mAwbLayout.setAnimation(anim);
        mAwbLayout.setVisibility(View.GONE);
    }

    public void clearAllFlashTextBackground(int id) {
        tv_flashClose.setBackground(null);
        tv_flashOpen.setBackground(null);
        tv_flashKeepOpen.setBackground(null);
        tv_flashAuto.setBackground(null);
        findViewById(id).setBackground(getResources().getDrawable(R.drawable.flash_text_shape));
    }

    public void clearAllAwbTextBackground(int id) {
        tv_awb_close.setBackground(null);
        wb_auto.setBackground(null);
        wb_cloudy_daylight.setBackground(null);
        wb_daylight.setBackground(null);
        wb_fluorescent.setBackground(null);
        wb_incandescent.setBackground(null);
        wb_shade.setBackground(null);
        wb_twilight.setBackground(null);
        wb_warm_fluorescent.setBackground(null);
        findViewById(id).setBackground(getResources().getDrawable(R.drawable.flash_text_shape));
    }

    /**
     * 计算需要的使用的摄像头分辨率
     * @return
     */
    private Size  getMatchingSize2(){
        Size selectSize = null;
        try {
            CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics(String.valueOf(mCameraID));
            StreamConfigurationMap streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            Size[] sizes = streamConfigurationMap.getOutputSizes(ImageFormat.JPEG);
            DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); //因为我这里是将预览铺满屏幕,所以直接获取屏幕分辨率
            int deviceWidth = displayMetrics.widthPixels; //屏幕分辨率宽
            int deviceHeigh = displayMetrics.heightPixels; //屏幕分辨率高
            Log.e(TAG, "getMatchingSize2: 屏幕密度宽度="+deviceWidth);
            Log.e(TAG, "getMatchingSize2: 屏幕密度高度="+deviceHeigh );
            /**
             * 循环40次,让宽度范围从最小逐步增加,找到最符合屏幕宽度的分辨率,
             * 你要是不放心那就增加循环,肯定会找到一个分辨率,不会出现此方法返回一个null的Size的情况
             * ,但是循环越大后获取的分辨率就越不匹配
             */
            for (int j = 1; j < 41; j++) {
                for (int i = 0; i < sizes.length; i++) { //遍历所有Size
                    Size itemSize = sizes[i];
                    Log.e(TAG,"当前itemSize 宽="+itemSize.getWidth()+"高="+itemSize.getHeight());
                    //判断当前Size高度小于屏幕宽度+j*5  &&  判断当前Size高度大于屏幕宽度-j*5  &&  判断当前Size宽度小于当前屏幕高度
                    //TODO 这里没有符合要求的值导致下面的代码中width为空
//                    if (itemSize.getHeight() < (deviceWidth + j*5) && itemSize.getHeight() > (deviceWidth - j*5)) {
                    if (itemSize.getHeight() < (deviceWidth + j*5) && itemSize.getWidth() > (deviceWidth - j*5)) {

                        Log.e(TAG,"选出的 宽="+itemSize.getWidth()+"选出的 高="+itemSize.getHeight());

                        if (selectSize != null){ //如果之前已经找到一个匹配的宽度
                            if (Math.abs(deviceHeigh-itemSize.getWidth()) < Math.abs(deviceHeigh - selectSize.getWidth())){ //求绝对值算出最接近设备高度的尺寸
                                selectSize = itemSize;
                                continue;
                            }
                        }else {
                            selectSize = itemSize;
                            Log.d(TAG, "查看是否到达这一步");
                        }

                    }
                }
                if (selectSize != null){ //如果不等于null 说明已经找到了 跳出循环
                    break;
                }
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        Log.e(TAG, "getMatchingSize2: 选择的分辨率宽度="+selectSize.getWidth());
        Log.e(TAG, "getMatchingSize2: 选择的分辨率高度="+selectSize.getHeight());
        return selectSize;
    }

//    /**
//     * 设置点击方法
//     */
//    private void setClick() {
//        //mPreview.setOnClickListener(new CustomcameraClick());
//        mTextureView.setOnClickListener(new CustomcameraClick());
////        btn_cancel_aca.setOnClickListener(new CustomcameraClick());
////        btn_ok_aca.setOnClickListener(new CustomcameraClick());
//        btn_photo_aca.setOnClickListener(new CustomcameraClick());
//        //录像点击方法
//        btn_video_aca.setOnClickListener(new CustomcameraClick());
//        btn_switch.setOnClickListener(new CustomcameraClick());
//    }
//
//    /**
//     * 代码初始化
//     */
//    private void initView() {
//        //mPreview = findViewById(R.id.preview);//初始化预览界面
//        mTextureView = findViewById(R.id.textureview);//初始化预览界面
////        btn_cancel_aca = findViewById(R.id.btn_cancel_aca);//取消按钮
////        btn_ok_aca = findViewById(R.id.btn_ok_aca);//确定按钮
//        btn_photo_aca = findViewById(R.id.btn_photo_aca);//拍照按钮
//
//        btn_video_aca = findViewById(R.id.btn_video_aca);//录像按钮
//        btn_switch = findViewById(R.id.btn_switch);//摄像头切换
//
//        //延时时间的存储
//        sharedPreferences = getSharedPreferences("time", MODE_PRIVATE);
//        editor = sharedPreferences.edit();
//        ed_time = findViewById(R.id.ed_time);//时间输入框
//        time_show = findViewById(R.id.time_show);//显示时间
//
//        //在每次初始化达到重启相机并且获得延迟时间的值
//        time = sharedPreferences.getString("delaytime", "");//取时间值
//        if (time != null){
//            ed_time.setText(time);//在相机再次启动的时候将之前存储的值传给输入框
//        }
//    }
//
//    //定义时间存储方法
//    public void delaytime(){
//        String time = ed_time.getText().toString().trim();//获取编辑框时间
//        editor.putString("delaytime", time);//将时间值传入sharedPreferences
//        editor.apply();//editor.commit();也可以
//    }
//
//    //定义延时拍照线程
//    private Runnable timerRunnable = new Runnable() {
//        @Override
//        public void run() {
//            int times = Integer.parseInt(time);
//            for (; times > 0; times--){
//                time_show.setText("" + times);//.setText("" + times)括号中的参数类型必须为string
//                if (times > 0 ){
//                    try {
//                        Thread.sleep(1000);
//                        Log.d("延时", "run: 休眠1s");
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                }
//            }
//        }
//    };
//
//    //利用handler对象运行run方法，没有新建函数，在现有函数中调用
//    private void runTimerRunnable(){
//        //handler.post(timerRunnable);
//        new Thread(timerRunnable).run();
//    }
//
//    //定义“拍照”方法
//    public void takePhoto() {
//        //配置如下：
//        Camera.Parameters parameters = mCamera.getParameters();// 获取相机参数集
//        List<Camera.Size> SupportedPreviewSizes =
//                parameters.getSupportedPreviewSizes();// 获取支持预览照片的尺寸
//        Camera.Size previewSize = SupportedPreviewSizes.get(0);// 从List取出Size
//        parameters.setPreviewSize(previewSize.width, previewSize.height);//
//        //  设置预览照片的大小
//        List<Camera.Size> supportedPictureSizes =
//                parameters.getSupportedPictureSizes();// 获取支持保存图片的尺寸
//        Camera.Size pictureSize = supportedPictureSizes.get(0);// 从List取出Size
//        parameters.setPictureSize(pictureSize.width, pictureSize.height);//
//        // 设置照片的大小
//        mCamera.setParameters(parameters);
//
//        //摄像头聚焦
//        mCamera.autoFocus(new Camera.AutoFocusCallback() {
//            @Override
//            public void onAutoFocus(boolean success, Camera camera) {
//                if (success) {
//                    mCamera.takePicture(null, null, mpictureCallback);
//                }
//            }
//        });
//
//    }
//
//    //activity生命周期在onResume是界面应是显示状态
//    @Override
//    protected void onResume() {
//        super.onResume();
//        if (mCamera == null) {//如果此时摄像头值仍为空
//            mCamera = getCamera();//则通过getCamer a()方法开启摄像头
//            //if (mHolder != null) {//被用TextureView的属性替换
//            if (mTexture != null) {
//                //setStartPreview(mCamera, mHolder);//开启预览界面
//                setStartPreview(mCamera, mTexture);//开启预览界面
//            }
//        }
//    }
//
//    //activity暂停的时候释放摄像头
//    @Override
//    protected void onPause() {
//        super.onPause();
//        releaseCamera();
//    }
//
//    //onResume()中提到的开启摄像头的方法
//    private Camera getCamera() {
//        Camera camera;//声明局部变量camera
//        try {
//            camera = Camera.open(cameraId);
//        }//根据cameraId的设置打开前置摄像头
//        catch (Exception e) {
//            camera = null;
//            e.printStackTrace();
//        }
//        return camera;
//    }
//
//    //切换摄像头
//    private void switchCamera(){
//        if (cameraId == 0){
//            //先关闭摄像头
//            releaseCamera();
//            cameraId = 1;
//
//        }else if (cameraId == 1){
//            //先关闭摄像头
//            releaseCamera();
//            cameraId = 0;
//        }
//        mCamera = getCamera();
//        setStartPreview(mCamera, mTexture);
//    }
//
//    //开启预览界面
//    //private void setStartPreview(Camera camera, SurfaceHolder holder) {
//    private void setStartPreview(Camera camera, SurfaceTexture texture) {
//        try {
//            //camera.setPreviewDisplay(holder);//被下一行用TextureView的属性替换
////            camera.setPreviewTexture(texture);
//            camera.setPreviewTexture(mTextureView.getSurfaceTexture());
//
//            camera.setDisplayOrientation(90);//如果没有这行你看到的预览界面就会是水平的
//            camera.startPreview();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
//
//    //定义释放摄像头的方法
//    private void releaseCamera() {
//        if (mCamera != null) {//如果摄像头还未释放，则执行下面代码
//            mCamera.stopPreview();//1.首先停止预览
//            mCamera.setPreviewCallback(null);//2.预览返回值为null
//            mCamera.release(); //3.释放摄像头
//            mCamera = null;//4.摄像头对象值为null
//        }
//    }
//
//    //定义新建预览界面的方法
////    @Override
////    public void surfaceCreated(SurfaceHolder holder) {
////        setStartPreview(mCamera, mHolder);
////    }
////
////    @Override
////    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
////        mCamera.stopPreview();//如果预览界面改变，则首先停止预览界面
////        setStartPreview(mCamera, mHolder);//调整再重新打开预览界面
////    }
////
////    @Override
////    public void surfaceDestroyed(SurfaceHolder holder) {
////        releaseCamera();//预览界面销毁则释放相机
////    }
//
//    @Override
//    public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
//        setStartPreview(mCamera, (SurfaceTexture) mTexture);
//    }
//
//    @Override
//    public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
//
//    }
//
//    @Override
//    public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
//        //mCamera.stopPreview();//如果预览界面改变，则首先停止预览界面
//        setStartPreview(mCamera, (SurfaceTexture) mTexture);//调整再重新打开预览界面
//        releaseCamera();//预览界面销毁则释放相机
//        return false;
//    }
//
//    @Override
//    public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
////        mCamera.stopPreview();//如果预览界面改变，则首先停止预览界面
////        setStartPreview(mCamera, (SurfaceTexture) mTexture);//调整再重新打开预览界面
//    }
//
//    //拍照声音
//    private MediaPlayer mediaPlayer;
//    private AudioManager audioManager;
//
//    private void tmusic() {
//        audioManager = (AudioManager) getSystemService(Service.AUDIO_SERVICE);
//        mediaPlayer = MediaPlayer.create(this, R.raw.music);
////        mediaPlayer.setLooping(true);//循环播放声音
//        mediaPlayer.start();
//
//    }
//
//
//
//    private class CustomcameraClick implements View.OnClickListener {
//
//        @Override
//        public void onClick(View v) {
//            switch (v.getId()) {
//                //case R.id.preview://点击预览界面聚焦
//                case R.id.textureview://点击预览界面聚焦
//                    mCamera.autoFocus(null);
//                    break;
////                case R.id.btn_cancel_aca://取消按钮
////                    finish();
////                    break;
////                case R.id.btn_ok_aca:
////                    Toast.makeText(Customcamera.this, "确定按钮", Toast.LENGTH_SHORT).show();
////                    break;
//                case R.id.btn_photo_aca://拍照按钮
//                    tmusic();
//                    delaytime();//延时时间
//                    runTimerRunnable();
//                    takePhoto();
//                    break;
//
//                //录像按钮
//                case R.id.btn_video_aca:
////                    findViewById(R.id.btn_stopvideo_aca).setVisibility(View.VISIBLE);
////                    findViewById(R.id.btn_startvideo_aca).setVisibility(View.GONE);
//                    Intent intent = new Intent().setClass(Customcamera.this,Videocamera.class);
//                    startActivity(intent);
//                    break;
//                case R.id.btn_switch:
//                    Log.d("提示：", "onClick: 切换摄像头");
//                    switchCamera();
//                    break;
//
//                default:
//                    break;
//            }
//        }
//    }




}
